/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package coursevoitures;
import bluenext.CommonInterface;
import bluenext.ErreurNXTException;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import tools.CourseVoituresException;
import wiimote.Wiimote_Connecteur;

import java.util.Vector;
import wiiusej.Wiimote;


/**
 * Classe contenant les "regles metier" de l'application.
 * @author Aurelien
 */
public class Ctrl {

    private GUI gui;
    private CommonInterface ci;
    private Wiimote_Connecteur wiimoteConn;

    private int puissanceMoteur=80;
    
    private Vector listeCoupleWiimoteNXT;

    /**
     * Constructeur de la classe, il cree la liste de couple wiimote/nxt, l'interface graphique, l'interface commune BlueNeXT et un objet pour la connexion des Wiimotes.
     */
    public Ctrl(){
        listeCoupleWiimoteNXT = new Vector();
        gui = new GUI(this);
        ci = new CommonInterface();
        wiimoteConn = new Wiimote_Connecteur(this);

        gui.setVisible(true);
    }

    /**
     * Methode permettant de faire le lien entre l'IHM et le connecteur de wiimote.
     * @return l'identifiant de la Wiimote connectee ou un code erreur (AUCUNE_WIIMOTE ou AUCUNE_NOUVELLE_WIIMOTE)
     */
    public int[] connecter_wiimote(){
        int id[]=new int[1]; // = CourseVoituresException.AUCUNE_WIIMOTE;;
        try {            
            Wiimote[] tmp = wiimoteConn.connecter_wiimote();
            //System.out.println("Dans Ctrl.connecter_wiimote - tmp.length : "+tmp.length);
            if (tmp != null) {
                id = new int [tmp.length];
                for(int i = 0; i< tmp.length; i++){
                    wiimoteConn.ajouter_Wiimote(tmp[i]);
                    id[i] = tmp[i].getId();
                }
            }
            
        } catch (CourseVoituresException ex) {
            id[0] = ex.getTypeException();
            System.out.println(ex);
        }
        catch (Exception ex){
            System.out.println(ex);
        }
        finally{
            return id;
        }
    }

    /**
     * Methode permettant de faire le lien entre l'IHM et l'interface commune BlueNeXT pour faire uen recherche de NXT a proximite.
     * @return un tableau de nom de NXT.
     */
    public String[] rechercher_NXT(){
        try {
            return ci.search();
        } catch (ErreurNXTException ex) {
            Logger.getLogger(Ctrl.class.getName()).log(Level.SEVERE, null, ex);
            return null;
        }
    }

    /**
     * Methode permettant d'associer une wiimote et un NXT.
     * @param idWiimote l'identifiant de la wiimote.
     * @param nomNXT le nom du NXT.
     * @return true en cas de reussite, false sinon.
     */
    public boolean associer_Wiimote_NXT(int idWiimote, String nomNXT){
        boolean flag = false;
        try {
            Wiimote w = wiimoteConn.chercher_Wiimote_Par_Id(idWiimote);
            System.out.println("Tentative d'association de "+idWiimote+" avec "+nomNXT);
            ci.connect(nomNXT);
            
            listeCoupleWiimoteNXT.add(new CoupleWiimoteNXT(w, nomNXT));
            flag = true;
        } catch (ErreurNXTException ex) {
            Logger.getLogger(Ctrl.class.getName()).log(Level.SEVERE, null, ex);
        }
        finally{
            return flag;
        }
    }

    
    public boolean associer_Wiimote_NXT_Par_Adresse(int idWiimote, String nomNXT, String adresseNXT){
        boolean flag = false;
        try {
            Wiimote w = wiimoteConn.chercher_Wiimote_Par_Id(idWiimote);
            System.out.println("Tentative d'association de "+idWiimote+" le NXT "+nomNXT+" d'adresse "+adresseNXT);
            ci.connect(nomNXT, adresseNXT);

            listeCoupleWiimoteNXT.add(new CoupleWiimoteNXT(w, nomNXT));
            flag = true;
        } catch (ErreurNXTException ex) {
            Logger.getLogger(Ctrl.class.getName()).log(Level.SEVERE, null, ex);
        }
        finally{
            return flag;
        }
    }

    /**
     * Methode permettant de deconnecter une wiimote et de couper la connexion avec le NXT associe.
     * @param idWiimote l'identifiant de la Wiimote a deconnecter.
     * @return true en cas de reussite, false sinon.
     */
    public boolean deconnecter_Wiimote(int idWiimote){
        boolean flag = false;
        CoupleWiimoteNXT c;

        Wiimote w = wiimoteConn.chercher_Wiimote_Par_Id(idWiimote);
        if (w != null){
            try {
                c = chercher_Couple_Wiimote_NXT_Par_IdWiimote(idWiimote);
                if (c != null && c.getNxt()!=null){
                    ci.disconnect(c.getNxt());
                    gui.enlever_couple_wiimote_nxt(w.getId(), c.getNxt());
                }

                w.setLeds(false, false, false, false);
                w.disconnect();

                wiimoteConn.enlever_wiimote(w);
                gui.enlever_id_wiimote(w.getId());                

                flag = true;
            } catch (IOException ex) {
                Logger.getLogger(Ctrl.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        return flag;
    }

    /**
     * Methode permettant de faire le lien entre le controleur d'evenement Wiimote et l'interface BlueNeXT pour faire biper un NXT.
     * @param idWiimote l'identifiant de la Wiimote qui a genere l'evenement.
     */
    public void bip(int idWiimote){
        CoupleWiimoteNXT tmp = chercher_Couple_Wiimote_NXT_Par_IdWiimote(idWiimote);

        if(tmp != null){
            try {
                ci.playTone(tmp.getNxt(), 8000, 5);
            } catch (IOException ex) {
                Logger.getLogger(Ctrl.class.getName()).log(Level.SEVERE, null, ex);
            } catch (ErreurNXTException ex) {
                Logger.getLogger(Ctrl.class.getName()).log(Level.SEVERE, null, ex);
            }
        }else{
            javax.swing.JOptionPane.showMessageDialog(null, "Aucun NXT associe a la Wiimote "+idWiimote);
        }
    }

    /**
     * Methode permettant de faire le lien entre le controleur d'evenement Wiimote et l'interface BlueNeXT pour faire avancer un NXT.
     * @param idWiimote l'identifiant de la Wiimote qui a genere l'evenement.
     */
    public void avancer(int idWiimote){
        try {            
            CoupleWiimoteNXT tmp = chercher_Couple_Wiimote_NXT_Par_IdWiimote(idWiimote);
            if(tmp != null){
                ci.setOutputState(tmp.getNxt(), 0, Byte.parseByte("-"+puissanceMoteur), lejos.nxt.remote.NXTProtocol.MOTORON, lejos.nxt.remote.NXTProtocol.REGULATED, 80, lejos.nxt.remote.NXTProtocol.MOTOR_RUN_STATE_RUNNING, 0);
                ci.setOutputState(tmp.getNxt(), 1, Byte.parseByte("-"+puissanceMoteur), lejos.nxt.remote.NXTProtocol.MOTORON, lejos.nxt.remote.NXTProtocol.REGULATED, 80, lejos.nxt.remote.NXTProtocol.MOTOR_RUN_STATE_RUNNING, 0);
            }else{
                javax.swing.JOptionPane.showMessageDialog(null, "Aucun NXT associe a la Wiimote "+idWiimote);
            }

        } catch (IOException ex) {
            Logger.getLogger(Ctrl.class.getName()).log(Level.SEVERE, null, ex);
        } catch (ErreurNXTException ex) {
            Logger.getLogger(Ctrl.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /**
     * Methode permettant de faire le lien entre le controleur d'evenement Wiimote et l'interface BlueNeXT pour faire reculer un NXT.
     * @param idWiimote l'identifiant de la Wiimote qui a genere l'evenement.
     */
    public void reculer(int idWiimote){
        try {
            CoupleWiimoteNXT tmp = chercher_Couple_Wiimote_NXT_Par_IdWiimote(idWiimote);
            if (tmp != null){
                ci.setOutputState(tmp.getNxt(), 0, Byte.parseByte(""+puissanceMoteur), lejos.nxt.remote.NXTProtocol.MOTORON, lejos.nxt.remote.NXTProtocol.REGULATED, 80, lejos.nxt.remote.NXTProtocol.MOTOR_RUN_STATE_RUNNING, 0);
                ci.setOutputState(tmp.getNxt(), 1, Byte.parseByte(""+puissanceMoteur), lejos.nxt.remote.NXTProtocol.MOTORON, lejos.nxt.remote.NXTProtocol.REGULATED, 80, lejos.nxt.remote.NXTProtocol.MOTOR_RUN_STATE_RUNNING, 0);
            }else{
                javax.swing.JOptionPane.showMessageDialog(null, "Aucun NXT associe a la Wiimote "+idWiimote);
            }
        } catch (IOException ex) {
            Logger.getLogger(Ctrl.class.getName()).log(Level.SEVERE, null, ex);
        } catch (ErreurNXTException ex) {
            Logger.getLogger(Ctrl.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /**
     * Methode permettant de faire le lien entre le controleur d'evenement Wiimote et l'interface BlueNeXT pour faire tourner a gauche un NXT.
     * @param idWiimote l'identifiant de la Wiimote qui a genere l'evenement.
     */
    public void tournerGauche(int idWiimote){
        try {
            CoupleWiimoteNXT tmp = chercher_Couple_Wiimote_NXT_Par_IdWiimote(idWiimote);
            if (tmp != null){
                ci.setOutputState(tmp.getNxt(), 0, Byte.parseByte("-"+puissanceMoteur), lejos.nxt.remote.NXTProtocol.MOTORON, lejos.nxt.remote.NXTProtocol.REGULATED, 80, lejos.nxt.remote.NXTProtocol.MOTOR_RUN_STATE_RUNNING, 0);
                ci.setOutputState(tmp.getNxt(), 1, Byte.parseByte(""+puissanceMoteur), lejos.nxt.remote.NXTProtocol.MOTORON, lejos.nxt.remote.NXTProtocol.REGULATED, 80, lejos.nxt.remote.NXTProtocol.MOTOR_RUN_STATE_RUNNING, 0);
            }else{
                javax.swing.JOptionPane.showMessageDialog(null, "Aucun NXT associe a la Wiimote "+idWiimote);
            }
        } catch (IOException ex) {
            Logger.getLogger(Ctrl.class.getName()).log(Level.SEVERE, null, ex);
        } catch (ErreurNXTException ex) {
            Logger.getLogger(Ctrl.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /**
     * Methode permettant de faire le lien entre le controleur d'evenement Wiimote et l'interface BlueNeXT pour faire tourner a droite un NXT.
     * @param idWiimote l'identifiant de la Wiimote qui a genere l'evenement.
     */
    public void tournerDroite(int idWiimote){
        try {
            CoupleWiimoteNXT tmp = chercher_Couple_Wiimote_NXT_Par_IdWiimote(idWiimote);
            if(tmp != null){
                ci.setOutputState(tmp.getNxt(), 0, Byte.parseByte(""+puissanceMoteur), lejos.nxt.remote.NXTProtocol.MOTORON, lejos.nxt.remote.NXTProtocol.REGULATED, 80, lejos.nxt.remote.NXTProtocol.MOTOR_RUN_STATE_RUNNING, 0);
                ci.setOutputState(tmp.getNxt(), 1, Byte.parseByte("-"+puissanceMoteur), lejos.nxt.remote.NXTProtocol.MOTORON, lejos.nxt.remote.NXTProtocol.REGULATED, 80, lejos.nxt.remote.NXTProtocol.MOTOR_RUN_STATE_RUNNING, 0);
            }else{
                javax.swing.JOptionPane.showMessageDialog(null, "Aucun NXT associe a la Wiimote "+idWiimote);
            }
        } catch (IOException ex) {
            Logger.getLogger(Ctrl.class.getName()).log(Level.SEVERE, null, ex);
        } catch (ErreurNXTException ex) {
            Logger.getLogger(Ctrl.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /**
     * Methode permettant de faire le lien entre le controleur d'evenement Wiimote et l'interface BlueNeXT pour faire arreter un NXT.
     * @param idWiimote l'identifiant de la Wiimote qui a genere l'evenement.
     */
    public void stopRobot(int idWiimote){
        try {
            CoupleWiimoteNXT tmp = chercher_Couple_Wiimote_NXT_Par_IdWiimote(idWiimote);
            if(tmp != null){
                ci.setOutputState(tmp.getNxt(), 0, Byte.parseByte("0"), lejos.nxt.remote.NXTProtocol.MOTORON, lejos.nxt.remote.NXTProtocol.REGULATED, 80, lejos.nxt.remote.NXTProtocol.MOTOR_RUN_STATE_RUNNING, 0);
                ci.setOutputState(tmp.getNxt(), 1, Byte.parseByte("0"), lejos.nxt.remote.NXTProtocol.MOTORON, lejos.nxt.remote.NXTProtocol.REGULATED, 80, lejos.nxt.remote.NXTProtocol.MOTOR_RUN_STATE_RUNNING, 0);
            }
        } catch (IOException ex) {
            Logger.getLogger(Ctrl.class.getName()).log(Level.SEVERE, null, ex);
        } catch (ErreurNXTException ex) {
            Logger.getLogger(Ctrl.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void avancerEtDroite(int idWiimote){
        try {
            CoupleWiimoteNXT tmp = chercher_Couple_Wiimote_NXT_Par_IdWiimote(idWiimote);
            if(tmp != null){
                ci.setOutputState(tmp.getNxt(), 0, Byte.parseByte("-40"), lejos.nxt.remote.NXTProtocol.MOTORON, lejos.nxt.remote.NXTProtocol.REGULATED, 80, lejos.nxt.remote.NXTProtocol.MOTOR_RUN_STATE_RUNNING, 0);
                ci.setOutputState(tmp.getNxt(), 1, Byte.parseByte("-80"), lejos.nxt.remote.NXTProtocol.MOTORON, lejos.nxt.remote.NXTProtocol.REGULATED, 80, lejos.nxt.remote.NXTProtocol.MOTOR_RUN_STATE_RUNNING, 0);
            }
        } catch (IOException ex) {
            Logger.getLogger(Ctrl.class.getName()).log(Level.SEVERE, null, ex);
        } catch (ErreurNXTException ex) {
            Logger.getLogger(Ctrl.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void avancerEtGauche(int idWiimote){
        try {
            CoupleWiimoteNXT tmp = chercher_Couple_Wiimote_NXT_Par_IdWiimote(idWiimote);
            if(tmp != null){
                ci.setOutputState(tmp.getNxt(), 0, Byte.parseByte("-80"), lejos.nxt.remote.NXTProtocol.MOTORON, lejos.nxt.remote.NXTProtocol.REGULATED, 80, lejos.nxt.remote.NXTProtocol.MOTOR_RUN_STATE_RUNNING, 0);
                ci.setOutputState(tmp.getNxt(), 1, Byte.parseByte("-40"), lejos.nxt.remote.NXTProtocol.MOTORON, lejos.nxt.remote.NXTProtocol.REGULATED, 80, lejos.nxt.remote.NXTProtocol.MOTOR_RUN_STATE_RUNNING, 0);
            }
        } catch (IOException ex) {
            Logger.getLogger(Ctrl.class.getName()).log(Level.SEVERE, null, ex);
        } catch (ErreurNXTException ex) {
            Logger.getLogger(Ctrl.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void reculerEtDroite(int idWiimote){
        try {
            CoupleWiimoteNXT tmp = chercher_Couple_Wiimote_NXT_Par_IdWiimote(idWiimote);
            if(tmp != null){
                ci.setOutputState(tmp.getNxt(), 0, Byte.parseByte("40"), lejos.nxt.remote.NXTProtocol.MOTORON, lejos.nxt.remote.NXTProtocol.REGULATED, 80, lejos.nxt.remote.NXTProtocol.MOTOR_RUN_STATE_RUNNING, 0);
                ci.setOutputState(tmp.getNxt(), 1, Byte.parseByte("80"), lejos.nxt.remote.NXTProtocol.MOTORON, lejos.nxt.remote.NXTProtocol.REGULATED, 80, lejos.nxt.remote.NXTProtocol.MOTOR_RUN_STATE_RUNNING, 0);
            }
        } catch (IOException ex) {
            Logger.getLogger(Ctrl.class.getName()).log(Level.SEVERE, null, ex);
        } catch (ErreurNXTException ex) {
            Logger.getLogger(Ctrl.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void reculerEtGauche(int idWiimote){
        try {
            CoupleWiimoteNXT tmp = chercher_Couple_Wiimote_NXT_Par_IdWiimote(idWiimote);
            if(tmp != null){
                ci.setOutputState(tmp.getNxt(), 0, Byte.parseByte("40"), lejos.nxt.remote.NXTProtocol.MOTORON, lejos.nxt.remote.NXTProtocol.REGULATED, 80, lejos.nxt.remote.NXTProtocol.MOTOR_RUN_STATE_RUNNING, 0);
                ci.setOutputState(tmp.getNxt(), 1, Byte.parseByte("80"), lejos.nxt.remote.NXTProtocol.MOTORON, lejos.nxt.remote.NXTProtocol.REGULATED, 80, lejos.nxt.remote.NXTProtocol.MOTOR_RUN_STATE_RUNNING, 0);
            }
        } catch (IOException ex) {
            Logger.getLogger(Ctrl.class.getName()).log(Level.SEVERE, null, ex);
        } catch (ErreurNXTException ex) {
            Logger.getLogger(Ctrl.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /* ------------- PRIVATE ------------- */

    /**
     * Methode permettant de chercher un couple Wiimote/NXT en fonction de l'identifiant de la Wiimote.
     * @param idWiimote l'identifiant de la Wiimote.
     * @return le couple Wiimote/NXT ou null en cas d'echec.
     */
    private CoupleWiimoteNXT chercher_Couple_Wiimote_NXT_Par_IdWiimote(int idWiimote){
        CoupleWiimoteNXT tmp = null;
        CoupleWiimoteNXT res = null;

        for(int i=0; i < listeCoupleWiimoteNXT.size(); i++){
            tmp = (CoupleWiimoteNXT)listeCoupleWiimoteNXT.get(i);
            if (tmp.getWiimote().getId() == idWiimote){
                res=tmp;
                break;
            }
        }
        return res;
    }   
}
